package deferlearn

import (
	"fmt"
)

func DeferLearn() {
	fmt.Println("test1")
	//f, _ := os.Open("xxx.txt")
	//defer f.Close() //defer是go语言用于注册延迟调用的机制，他可以让当前函数执行完毕后执行。
	defer fmt.Println("defer test1") //defer之后，只能是函数调用，不能是表达式，比如a++

	defer fmt.Println("defer test2")
	defer fmt.Println("defer test3")
	//多个defer，调用的顺序是反的
	//是一个栈，后进先出

	panic("error")

	fmt.Println("test2")

}

func DeferCopy1() {
	//defer语句执行时的拷贝机制
	test := func() {
		fmt.Println("test1")
	}

	defer test()

	//test已经被defer，copy到栈里，后面再改逻辑无效
	test = func() {
		fmt.Println("test2")
	}
	fmt.Println("test3")
}

func DeferCopy2() {
	x := 10

	//10 -> 压栈的时候，x的值也被压进去了
	defer func(a int) {
		fmt.Println(a)
	}(x)

	//11 -> 虽然压栈了，但是引用类型
	defer func(a *int) {
		fmt.Println(*a)
	}(&x)

	//11 -> 这是个闭包，函数内部没有变量，会到外层找
	defer func() {
		fmt.Println(x)
	}()

	x++

}

func DeferAndReturn1() int {
	x := 10

	//是否意味着defer的函数里，影响不到外面的值？
	defer func() {
		x++
	}()

	//10
	return x

}

func DeferAndReturn2() *int {
	x := 10
	b := &x
	//是否意味着defer的函数里，影响不到外面的值？
	defer func() {
		*b++
	}()

	//在此函数外部，*b=11
	//如果此处返回*b,则值是10，因为defer在return后面
	return b

}
